Skip to content

02 打包软件

1. RPM 包

有两种RPM包:

  • source RPM (SRPM)
  • binary RPM

两者的文件格式和工具是相同的,但有不同的内容,服务于不同的目的。SRPM包含源代码,可选的补丁和SPEC文件,它描述了如何将源代码构建为二进制RPM。二进制RPM包含从源码和补丁构建的二进制文件。

1.1 RPM 打包工具

rpmdevtools 提供了一些打包工具,查看这些工具:

$ rpm -ql rpmdevtools | grep bin

1.2 RPM 打包工作区

使用rpmdev-setuptree设置目录布局,即RPM打包工作区:

$ rpmdev-setuptree

$ tree ~/rpmbuild/
/home/user/rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS

5 directories, 0 files
目录 Purpose
BUILD 当创建包时,各种%buildroot目录在这里创建。如果创建失败时,而日志输出又没有提供足够的信息,这将很有用处。
RPMS 二进制 RPMs 在这里创建,子目录表示不同的架构, 比如 x86_64noarch
SOURCES 压缩源码包和补丁存放地, rpmbuild 命令从这里寻找它们。
SPECS SPEC文件存放地
SRPMS rpmbuild创建 SRPM 时, SRPM 在这里创建

1.3 SPEC 文件

它通过在一系列章节中定义指令来告诉构建系统要做什么。

分为两个部分:Preamble(包含Body中使用的一系列元数据项。)和 Body(包含指令的主要部分)。

1.3.1 Preamble

SPEC 指令 定义
Name 包的基础名,应该和 SPEC 文件名匹配。
Version 软件的上游版本
Release 此版本的软件发布的次数。 通常,设置初始值为1%{?dist},每次发布新的时候就增加它。当新的 Version 构建时重置为1
Summary 包的在线简要介绍
License 被打包软件的 license 。
URL 关于软件的更多信息的完整 URL。
Source0 远端源代码的压缩存档的路径或 URL(未修补,修补程序在其他地方处理)。这应该指向存档的可访问和可靠的存储,例如上游页面,而不是打包的程序的本地存储。Path or URL to the compressed archive of the upstream source code (unpatched, patches are handled elsewhere). This should point to an accessible and reliable storage of the archive, for example, the upstream page and not the packager’s local storage. If needed, more SourceX directives can be added, incrementing the number each time, for example: Source1, Source2, Source3, and so on.
Patch0 应用到源码的第一个补丁。 If needed, more PatchX directives can be added, incrementing the number each time, for example: Patch1, Patch2, Patch3, and so on. 使用方法举例:%patch0 -p1
BuildArch 如果包不依赖架构,比如全部使用解释型编程语言编写,设置为 BuildArch: noarch。如果不设置,包自动继承构建机器的架构,比如 x86_64
BuildRequires 构建时用编译语言编写的程序所需的包列表。使用逗号或空格分隔。There can be multiple entries of BuildRequires, each on its own line in the SPEC file.
Requires 软件在安装后运行时所需的软件包。使用逗号或空格分隔。 There can be multiple entries of Requires, each on its own line in the SPEC file.
ExcludeArch 如果软件无法在特定处理器架构上运行,则可以在此处排除该体系结构。

1.3.2 Body

SPEC 指令 定义
%description RPM中打包的软件的完整描述。该描述可以跨越多行并且可以分成段落。
%prep 用于准备要构建的软件的命令或一系列命令,例如,在Source0中解压缩归档文件。该指令可以包含shell脚本。主要动作(参考《鸟哥的linux私房菜》):
1. 进行软件的补丁 (patch) 等相关工作;
2. 寻找软件所需要的目录是否已经存在?
3. 事先建立你的软件所需要的目录,或者事先需要进行的任务;
4. 如果待安装的 Linux 系统内已经有安装的时候可能会被覆盖掉的文件时,那么就必需要进行备份(backup)的工作。
%build 用于将软件构建为机器码(用于编译语言)或字节码(用于某些解释语言)的命令或一系列命令。
%install 用于将所需构建工件从%builddir(构建发生的位置)复制到%buildroot目录(包含要打包的文件的目录结构)的命令或一系列命令。通常意味着从~/rpmbuild/BUILD 复制文件到~/rpmbuild/BUILDROOT 并创建在~/rpmbuild/BUILDROOT中的必需的目录。这只在创建包的时候运行,而不是最终用户安装包的时候。 See Working with SPEC files for details.
%check 测试软件的命令或一系列命令。通常包含单元测试。
%files 将在最终用户的系统中安装的文件列表。
%changelog 不同版本或发布版本之间的包发生的更改记录。记录的是打包的改变,而不是软件的改变。

1.4 BuildRoots

充当在构建时最终用户的文件系统的根目录。构建文件的放置应符合最终用户系统的文件系统层次结构标准。

buildroot中的文件待会会被放到一个 cpio 的打包文件,将成为 RPM 的主要部分。当RPM安装之后,这些文件会被提取到根目录,并保留当前的目录结构。

1.5 RPM 宏

rpm macro是直接文本替换。被这意味着可以让RPM为您执行文本替换。

若不知道某个宏的值,可以使用rpm --eval %{_MACRO}查看:

$ rpm --eval %{_bindir}
/usr/bin

$ rpm --eval %{_libexecdir}
/usr/libexec

1.6 使用 SPEC 文件

不必手动创建,可以使用rpmdev-newspec 工具创建未填写内容的 SPEC 文件。

$ rpmdev-newspec cello

下面举例说明三种源码的 SPEC 文件。

1.6.1 Natively Compiled Code

Name:           cello
Version:        1.0
Release:        1%{?dist}
Summary:        hello world example implemented in C.

License:        GPLv3
URL:            http://www.sharkshark.xyz/%{name}
Source0:        http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz
Patch0:         cello-output-first-patch.patch

BuildRequires:  gcc make

%description
long description in C.


%prep
%setup -q


%build
make %{?_smp_mflags}


%install
%make_install


%files
%license LICENSE
%{_bindir}/%{name}


%changelog
* Tue Jul 23 2019 sharkshark <xxx@example.com> - 1.0-1
- First cello package

1.6.2 Raw Interpreted Code

Name:           bello
Version:        0.1
Release:        1%{?dist}
Summary:        hello world programed in bash.

License:        GPLv3
URL:            http://www.sharkshark.xyz/%{name}
Source0:        http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz

BuildArch:      noarch
Requires:       bash

%description
assume there is a long description


%prep
%setup -q


%build


%install
mkdir -p %{buildroot}/%{_bindir}
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}


%files
%license LICENSE
%{_bindir}/%{name}


%changelog
* Mon Jul 22 2019 sharkshark <xxx@example.com> - 0.1-1
- First bello package
- Example secod item in the changlog for version-release 0.1-1

1.6.3 Byte-Compiled Code

Name:           pello
Version:        0.1.1
Release:        1%{?dist}
Summary:        Hello World example implemented in Python

License:        GPLv3
URL:            http://www.sharkshark.xyz/%{name}
Source0:        http://www.sharkshark.xyz/%{name}/release/%{name}-%{version}.tar.gz

BuildRequires:  python
Requires:       python,bash
BuildArch:      noarch

%description
assume this is a long description.

%prep
%setup -q


%build
python -m compileall pello.py


%install
mkdir -p %{buildroot}/%{_bindir}
mkdir -p %{buildroot}/usr/lib/%{name}

cat > %{buildroot}/%{_bindir}/%{name} <<-EOF
#!/bin/bash
/usr/bin/python /usr/lib/%{name}/%{name}.pyc
EOF

chmod 0755 %{buildroot}/%{_bindir}/%{name}

install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/


%files
%license LICENSE
%dir /usr/lib/%{name}/
%{_bindir}/%{name}
/usr/lib/%{name}/%{name}.py*


%changelog
* Tue Jul 23 2019 sharkshark <xxx@example.com> - 0.1.1-1
- First pello package

2. 构建 RPM 包

2.1 Source RPMs

为什么要构建源码包?

  1. 为了保存一个RPM包的某些源文件。包括 SPEC 文件、源码、所有的补丁。这对回溯历史和debug很有用。
  2. 为了能够在不同的硬件平台或架构上构建二进制包。
$ rpmbuild -bs _SPECFILE_
$ cd ~/rpmbuild/SPECS/

$ rpmbuild -bs bello.spec
warning: bogus date in %changelog: Mon Jun 22 2019 sharkshark <xxx@example.com> - 0.1-1
Wrote: /home/study/rpmbuild/SRPMS/bello-0.1-1.el7.src.rpm

2.2 Binary RPMS

两种构建二进制RPM的方法:

  1. 使用rpmbuild --rebuild命令从SRPM重新构建
  2. 使用rpmbuild -bb命令从 SPEC 文件构建

2.2.1 从源码包构建

rpmbuild --bs cello.spec
rpmbuild --rebuild ../SRPMS/cello-1.0-1.el7.src.rpm

调用rpmbuild --rebuild包括以下几点:

  1. 安装SRPM的内容( SPEC 文件和源码)安装到rpmbuild目录

  2. 使用已安装的内容构建。

  3. 移除SPEC 文件和源码。如果想保留这两个文件,有下面两种方法:

    • 使用--recompile选项代替--rebuild

    • 使用rpm -Uvh SRPM命令安装源码包,这样两个文件又会重新出现在对应目录了。

2.2.2 从 SPEC 文件构建

rpmbuild --bb bello.spec

3. 检查RPMs是否合理

检查的是RPM包的质量,而不是软件本身的质量。主要使用rpmlint工具,可以检查:RPMs、SRPMs、 SPEC 文件。

rpmlint的规则很严格,有时可以跳过一些错误和警告。

yum install -y rpmlint